# import base64
# import pickle
#
# from django_redis import get_redis_connection
#
#
# class CartHelper:
#     def __init__(self, request, response=None, alias='cart'):
#         self.request = request
#         self.user = request.user
#         self.response = response
#
#         if request.user.is_authenticated:
#             # 如果用户已登录，创建 redis 链接
#             self.cart_key = 'cart_%s' % request.user.id
#             self.cart_selected_key = 'cart_selected_%s' % request.user.id
#             self.redis_conn = get_redis_connection(alias)
#
#     def _load_cookie_cart(self):
#         '''加载 cookie 中的购物车记录数据'''
#         cookie_cart = self.request.COOKIES.get('cart')
#
#         if cookie_cart:
#             cart_dict = pickle.loads(base64.b64decode(cookie_cart))
#         else:
#             cart_dict = {}
#
#         return cart_dict
#
#     def _set_cookie_cart(self, cart_dict):
#         '''设置 cookie 中的购物车记录数据'''
#         cookie_cart = base64.b64decode(pickle.dumps(cart_dict)).decode()
#         self.response.set_cookie('carts', cookie_cart, 30* 3600* 24)
#
#     def add_cart(self, sku_id, count, selected):
#         '''购物车记录添加
#         sku_id: 添加记录的商品id
#         count: 添加记录的商品数量
#         selected: 添加记录的勾选状态
#         '''
#         if self.user.is_authenticated:
#             # 用户已登录
#             # 创建 redis 管道 pipeline
#             pl = self.redis_conn.pipeline()
#
#             # hincrby key field balue: 如果 field 在hash 数据的字段中，已存在，其值会进行累加，否则就是添加
#             pl.hincrby(self.cart_key, sku_id, count)
#
#             if selected:
#                 # 如果记录被勾选，将记录添加到 set 集合中
#                 # sadd key member..:向 set 集合数据中添加元素
#                 pl.sadd(self.cart_selected_key, sku_id)
#             pl.execute()
#         else:
#             # 用户未登录
#             cart_dict = self._load_cookie_cart()
#
#             # 如果购物车中已添加该商品， 数量需要先进行累加
#             if sku_id in cart_dict:
#                 temp_count = count + cart_dict[sku_id]['count']
#             else:
#                 temp_count = count
#
#             cart_dict[sku_id] = {
#                 'count': count,
#                 'selected': selected
#             }
#
#             # 重新将购物车记录设置到1cookie 中
#             self._set_cookie_cart(cart_dict)
#
#     def get_cart(self):
#         '''购物车记录获取'''
#         if self.user.is_authenticated:
#             # 用户已登录
#             # 获取用户添加到购物车中的商品 ID 和对应的数量 count
#             # hgetall key: 获取 hash 数据中所有的  field 和 value
#             redis_cart = self.redis_conn.hgetall(self.cart_key)
#             # 获取用户购物车中被勾选的商品ID
#             # smembers key:获取 set 集合数据中的所有元素
#             selected_sku_ids = self.redis_conn.smembers(self.cart_selected_key)
#
#             cart_dict = {}
#
#             for sku_id, count in redis_cart.items():
#                 cart_dict[int(sku_id)] = {
#                     'count': int(count),
#                     'selected': sku_id in selected_sku_ids
#                 }
#         else:
#             # 用户未登录
#             # 从 cookie 数据中获取购物车数据
#             cart_dict = self._load_cookie_cart()
#
#         return cart_dict
#
#     def update_cart(self, sku_id, count, selected):
#         '''购物车记录修改
#         sku_id:修改记录的商品ID
#         count:修改记录的商品数量
#         selected:修改记录的勾选状态
#         '''
#         if self.user.is_authenticated:
#             # 用户已登录
#             pl = self.redis_conn.pipeline()
#             # 修改用户购物车中对应记录商品的数量
#             # hset key field value:将hash数据中指定 field字段的值设置为value
#             pl.hset(self.cart_key, sku_id, count)
#
#             # 修改用户购物车中对应记录商品的勾选状态
#             if selected:
#                 # sadd key member...:向set 集合数据中添加元素
#                 pl.sadd(self.cart_selected_key, sku_id)
#             else:
#                 # srem key member...: 从 set 集合数据中移除元素
#                 pl.srem(self.cart_selected_keym, sku_id)
#             pl.execute()
#         else:
#             # 用户未登录
#             cart_dict = self._load_cookie_cart()
#
#             # 修改购物车记录中指定商品的数量和勾选状态
#             cart_dict[sku_id] = {
#                 'count': count,
#                 'selected': selected
#             }
#             # 重新将购物车记录设置到cookie中
#             self._set_cookie_cart(cart_dict)
#
#     def remove_cart_cookie_cart(self, sku_id):
#         '''购物车记录删除
#         sku_id:删除记录的商品ID
#         '''
#         if self.user.is_authenticated:
#             # 用户已登录
#             pl = self.redis_conn.pipeline()
#
#             # 删除购物车记录一对应的商品及其数量
#             # hdel key field：删除 hash 数据中指定 field 字段及其值
#             pl.hdel(self.cart_key, sku_id)
#
#             # 删除购物车记录对应商品的勾选状态
#             # srem key member...:从set集合数据中移除元素
#             pl.srem(self.cart_selected_key, sku_id)
#             pl.execute()
#         else:
#             cart_dict = self._load_cookie_cart()
#             # 删除记录
#             cart_dict.pop(sku_id, None)
#
#             # 重新将购物车记录设置到 cookie中
#             self._set_cookie_cart(cart_dict)
#
#     def select_cart(self, selected):
#         '''购物车记录全选或取消全选'''
#         if self.user.is_authenticated:
#             sku_ids = self.redis_conn.hkeys(self.cart_key)
#
#             cart_selected_key = 'cart_selected_%s' % self.user.id
#             if selected:
#                 # 全选
#                 self.redis_conn.sadd(cart_selected_key, *sku_ids)
#                 # 非全选
#                 self.redis_conn.srem(cart_selected_key, *sku_ids)
#         else:
#             cart_dict = self._load_cookie_cart()
#             if cart_dict:
#                 for sku_id in cart_dict:
#                     cart_dict[sku_id]['selected'] = selected
#                 self._set_cookie_cart(cart_dict)
#     def get_redis_selected_cart(self):
#         '''获取redis中被勾选的记录'''
#         # sku_id count
#         redis_conn = self.redis_conn
#         redis_cart = redis_conn.hgetall(self.cart_key)
#         redis_selected = redis_conn.smembers(self.cart_selected_key)
#
#         cart_dict = {}
#         for sku_id, count in redis_cart.items():
#             if sku_id in redis_selected:
#                 cart_dict[int(sku_id)] = int(count)
#         return cart_dict
#
#     def clear_redis_selected_cart(self):
#         '''清楚redis中被勾选的记录'''
#         redis_conn = self.redis_conn
#         # redis_cart = redis_conn.hgetall(self.cart_key)
#         redis_selected = redis_conn.smembers(self.cart_selected_key)
#
#         redis_conn.hdel(self.cart_key, *redis_selected)
#         redis_conn.srem(self.cart_selected_key, *redis_selected)
#
#     def merge_cookie_cart_to_redis(self):
#         '''合并cookie的数据redis'''
#         # 获取cookie中的数据
#         cart_dict = self._load_cookie_cart()
#
#         if not cart_dict:
#             # 字典为空，不需要合并
#             return
#
#         # 根据合并方法进行合并操作
#         # 保存 cookie 购物车记录数据中对应商品的id及添加的数量count
#         carts = {}
#         # 保存 cookie 购物车记录数据中被勾选的记录对应商品的id
#         redis_cart_selected_add = []
#         # 保存 cookie 购物车记录数据中未被勾选的记录对应商品的id
#         redis_cart_selected_remove = []
#
#         for sku_id, count_selected in cart_dict.items():
#             carts[sku_id] = count_selected['count']
#
#             if count_selected['selected']:
#                 # 勾选
#                 redis_cart_selected_add.append(sku_id)
#             else:
#                 # 未勾选
#                 redis_cart_selected_remove.append(sku_id)
#
#         # 合并
#         # 将 cookie 购物车商品id和对应数量 count 合并到登录用户的redis hash 中
#         # hmset key field value field value...
#         self.redis_conn.hmset(self.cart_key, carts)
#
#         # 勾选状态合并到登录用户的 redis set 中
#         if redis_cart_selected_add:
#             self.redis_conn.sadd(self.cart_selected_key, *redis_cart_selected_add)
#
#         if redis_cart_selected_remove:
#             self.redis_conn.srem(self.cart_selected_key, *redis_cart_selected_remove)
#
#         # 清楚cookie中的购物车记录
#         # 删除cookie
#         self.response.delete_cookie('carts')

import json

from django.http import JsonResponse
from django.views import View

from carts.utils import CartHelper
from goods.models import SKU


# /cart/
class CartView(View):
    def post(self, request):
        """
        购物车数据新增：
        ① 获取参数并进行校验
        ② 根据用户是否登录，分别进行购物车数据的保存
        ③ 返回响应，购物车记录添加成功
        """
        # ① 获取参数并进行校验
        req_data = json.loads(request.body)
        sku_id = req_data.get('sku_id')
        count = req_data.get('count')
        selected = req_data.get('selected', True)

        if not all([sku_id, count]):
            return JsonResponse({'code': 400,
                                 'message': '缺少必传参数'})

        try:
            count = int(count)
        except Exception as e:
            return JsonResponse({'code': 400,
                                 'message': 'count参数有误'})

        if count <= 0:
            return JsonResponse({'code': 400,
                                 'message': 'count参数有误'})

        try:
            sku = SKU.objects.get(id=sku_id)
        except Exception as e:
            return JsonResponse({'code': 400,
                                 'message': 'sku商品不存在'})

        # ② 根据用户是否登录，分别进行购物车数据的保存
        response = JsonResponse({'code': 0,
                                 'message': '购物车添加成功',
                                 'count': count})

        try:
            cart_helper = CartHelper(request, response)
            cart_helper.add_cart(sku_id, count, selected)
        except Exception as e:
            return JsonResponse({'code': 400,
                                 'message': '购物车添加失败'})

        # ③ 返回响应，购物车记录添加成功
        return response

    def get(self, request):
        """
        购物车记录获取：
        ① 根据用户是否登录，分别进行购物车数据的获取
        ② 组织数据并返回响应
        """
        # ① 根据用户是否登录，分别进行购物车数据的获取
        try:
            cart_helper = CartHelper(request)
            cart_dict = cart_helper.get_cart()
        except Exception as e:
            return JsonResponse({'code': 400,
                                 'message': '购物车获取失败'})

        # ② 组织数据并返回响应
        try:
            skus = SKU.objects.filter(id__in=cart_dict.keys())
        except Exception:
            return JsonResponse({'code': 400,
                                 'message': '获取sku商品信息失败'})

        cart_skus = []

        for sku in skus:
            cart_skus.append({
                'id': sku.id,
                'name': sku.name,
                'price': sku.price,
                'default_image_url': 'http://192.168.19.131:8888/' + sku.default_image.name,
                'count': cart_dict[sku.id]['count'],
                'selected': cart_dict[sku.id]['selected'],
            })

        return JsonResponse({'code': 0,
                             'message': 'OK',
                             'cart_skus': cart_skus})

    def put(self, request):
        """
        购物车记录修改：
        ① 获取参数并进行校验
        ② 根据用户是否登录，分别修改购物车记录的数据
        ③ 返回响应
        """
        # ① 获取参数并进行校验
        req_data = json.loads(request.body)
        sku_id = req_data.get('sku_id')
        count = req_data.get('count')
        selected = req_data.get('selected', True)

        if not all([sku_id, count]):
            return JsonResponse({'code': 400,
                                 'message': '缺少必传参数'})

        try:
            count = int(count)
        except Exception as e:
            return JsonResponse({'code': 400,
                                 'message': 'count参数有误'})

        if count <= 0:
            return JsonResponse({'code': 400,
                                 'message': 'count参数有误'})

        try:
            sku = SKU.objects.get(id=sku_id)
        except Exception as e:
            return JsonResponse({'code': 400,
                                 'message': 'sku商品不存在'})

        # ② 根据用户是否登录，分别修改购物车记录的数据
        cart_sku = {
            'sku_id': sku_id,
            'count': count,
            'selected': selected
        }

        response = JsonResponse({'code': 0,
                                 'message': '购物车记录修改成功',
                                 'cart_sku': cart_sku})

        try:
            cart_helper = CartHelper(request, response)
            cart_helper.update_cart(sku_id, count, selected)
        except Exception as e:
            return JsonResponse({'code': 400,
                                 'message': '购物车记录修改失败'})

        return response

    def delete(self, request):
        """
        购物车记录删除：
        ① 获取参数并进行校验
        ② 根据用户是否登录，删除对应的购物车记录
        ③ 返回响应
        """
        # ① 获取参数并进行校验
        req_data = json.loads(request.body)
        sku_id = req_data.get('sku_id')

        if not sku_id:
            return JsonResponse({'code': 400,
                                 'message': '缺少必传参数'})

        # ② 根据用户是否登录，删除对应的购物车记录
        response = JsonResponse({'code': 0,
                                 'message': '购物车记录删除成功'})

        try:
            cart_helper = CartHelper(request, response)
            cart_helper.remove_cart_cookie_cart(sku_id)
        except Exception as e:
            return JsonResponse({'code': 400,
                                 'message': '购物车记录删除失败'})

        # ③ 返回响应
        return response


# PUT /carts/selection/
class CartSelectView(View):
    def put(self, request):
        """
        购物车记录全选和取消全选：
        ① 获取参数并进行校验
        ② 根据用户是否登录，对购物车记录进行全选和取消全选操作
        ③ 返回响应
        """
        # ① 获取参数并进行校验
        req_data = json.loads(request.body)
        selected = req_data.get('selected', True)

        # ② 根据用户是否登录，对购物车记录进行全选和取消全选操作
        response = JsonResponse({'code': 0,
                                 'message': '购物车记录操作成功'})
        try:
            cart_helper = CartHelper(request, response)
            cart_helper.select_cart(selected)
        except Exception as e:
            return JsonResponse({'code': 400,
                                 'message': '购物车记录操作失败'})

        # ③ 返回响应
        return response
